﻿#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
using System;
using UnityEngine;

namespace JH
{
    /// <summary>
    ///  处理数值边界的类
    /// </summary>
    public class BoundaryHandler : BasicMono<Vector2>
    {
        #region 数据范围

        /// <summary>
        ///  按照X值排序的处理器
        /// </summary>
        [SerializeField] [HideInInspector] private SortByX sortByX;

        /// <summary>
        ///  按照X值排序的处理器
        /// </summary>
        public SortByX SortByX => sortByX;

        /// <summary>
        ///  按照Y值排序的处理器
        /// </summary>
        [SerializeField] [HideInInspector] private SortByY sortByY;

        /// <summary>
        ///  按照Y值排序的处理器
        /// </summary>
        public SortByY SortByY => sortByY;

        /// <summary>
        ///  原始数据的X范围
        /// </summary>
        private Vector2 XDataRange => new(SortByX.Min.x, SortByX.Max.x);

        /// <summary>
        ///  原始数据的Y范围
        /// </summary>
        private Vector2 YDataRange => new(SortByY.Min.y, SortByY.Max.y);

        #endregion

        #region 自定义范围

        /// <summary>
        ///  自定义X轴范围
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("自定义X轴范围")]
#endif
        private bool customXRange;

        /// <summary>
        ///  自定义的X轴范围
        /// </summary>
#if ODIN_INSPECTOR
        [LabelText("X:最小值,最大值")]
        [ShowIf("customXRange")]
#endif
        [SerializeField]
        private Vector2 xCustomRange;

        /// <summary>
        ///  自定义Y轴范围
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("自定义Y轴范围")]
#endif
        public bool customYRange;

        /// <summary>
        ///  自定义的Y轴范围
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("Y:最小值,最大值")]
        [ShowIf("customYRange")]
#endif
        public Vector2 yCustomRange;

        #endregion

        #region 边界偏移量

        /// <summary>
        ///  顶部边界偏移，单位像素
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("顶部边界偏移")]
        [FoldoutGroup("设置偏移量")]
#endif
        private float top;

        /// <summary>
        ///  底部边界偏移，单位像素
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("底部边界偏移")]
        [FoldoutGroup("设置偏移量")]
#endif
        private float bottom;

        /// <summary>
        ///  左侧边界偏移，单位像素
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("左侧边界偏移")]
        [FoldoutGroup("设置偏移量")]
#endif
        private float left;

        /// <summary>
        ///  右侧边界偏移，单位像素
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("右侧边界偏移")]
        [FoldoutGroup("设置偏移量")]
#endif
        private float right;

        /// <summary>
        ///  偏移后的RectTransform的宽度
        /// </summary>
        private float OffsetWidth => Width - left - right;

        /// <summary>
        ///  偏移后的RectTransform的高度
        /// </summary>
        private float OffsetHeight => Height - top - bottom;

        /// <summary>
        ///  宽度缩放比例
        /// </summary>
        private float WidthScale => OffsetWidth / Width;

        /// <summary>
        ///  高度缩放比例
        /// </summary>
        private float HeightScale => OffsetHeight / Height;

        /// <summary>
        ///  UV偏移量
        /// </summary>
        private Vector2 UVOffset => new Vector2(left / Width, bottom / Height);

        #endregion

        #region Rect宽高

        /// <summary>
        ///  线渲染器
        /// </summary>
        private Vector2LineRender _lineRender;

        /// <summary>
        ///  获取线渲染器组件
        /// </summary>
        private Vector2LineRender LineRender => _lineRender ??= this.GetChartComp<Vector2LineRender, Vector2>(true);

        /// <summary>
        ///  RectTransform的宽度
        /// </summary>
        public float Width
        {
            get
            {
                return LineRender.rectTransform.rect.width;
                Rect r = LineRender.GetPixelAdjustedRect();
                return r.width;
            }
        }

        /// <summary>
        ///  RectTransform的高度
        /// </summary>
        public float Height
        {
            get
            {
                return LineRender.rectTransform.rect.height;
                Rect r = LineRender.GetPixelAdjustedRect();
                return r.height;
            }
        }

        #endregion

        /// <summary>
        ///  获取X轴的范围
        /// </summary>
        public Vector2 XRange => customXRange ? xCustomRange : XDataRange;

        /// <summary>
        ///  获取Y轴的范围
        /// </summary>
        public Vector2 YRange => customYRange ? yCustomRange : YDataRange;


        protected override void OnValidate()
        {
            sortByX = this.GetChart<Vector2>().GetProcessor<SortByX>();
            sortByY = this.GetChart<Vector2>().GetProcessor<SortByY>();
            base.OnValidate();
#if UNITY_EDITOR
            if (xCustomRange == Vector2.zero) xCustomRange = XDataRange;
            if (yCustomRange == Vector2.zero) yCustomRange = YDataRange;
            xRangeCache = XRange;
            yRangeCache = YRange;
#endif
        }

#if UNITY_EDITOR
        private void Update()
        {
            xRangeCache = XRange;
            yRangeCache = YRange;
        }
#endif

        #region 编辑器下用于展示数据的序列化字段

#if UNITY_EDITOR
        /// <summary>
        /// 编辑器下展示X轴范围
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("X轴范围")]
        [ReadOnly]
#endif
        private Vector2 xRangeCache;

        /// <summary>
        ///  编辑器下展示Y轴范围
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("Y轴范围")]
        [ReadOnly]
#endif
        private Vector2 yRangeCache;
#endif

        #endregion


        /// <summary>
        ///  传入一个数据点，计算UV坐标
        /// </summary>
        public Vector2 GetUVByOriginPoint(Vector2 origin)
        {
            //  UV = 原始UV * 缩放 + 偏移量
            var ret = UVOffset + new Vector2((origin.x - XRange.x) / (XRange.y - XRange.x) * WidthScale,
                (origin.y - YRange.x) / (YRange.y - YRange.x) * HeightScale);
            return new Vector2(Mathf.Clamp(ret.x, left / Width, 1 - right / Width),
                Mathf.Clamp(ret.y, bottom / Height, 1 - top / Height));
        }

        /// <summary>
        ///  获取UV坐标
        /// </summary>
        public Vector2 GetUVByOsPosition(Vector2 osPosition)
        {
            //  计算原始数据点
            var uv = new Vector2(osPosition.x / Width, osPosition.y / Height);
            return uv;
        }

        /// <summary>
        ///  获取模型空间位置
        /// </summary>
        public Vector2 GetOSPositionByUV(Vector2 uv)
        {
            return new Vector2(uv.x * Width, uv.y * Height);
        }

        /// <summary>
        ///  根据屏幕位置获取UV坐标
        /// </summary>
        public Vector2 GetUVByScreenPosition(Vector2 screenPosition)
        {
            // 屏幕坐标转换到RectTransform的局部坐标
            Vector2 localPosition = LineRender.GetComponent<RectTransform>().InverseTransformPoint(screenPosition);

            // 由于RectTransform的锚点约定为(0,0)，所以 UV = (localPosition.x / Width, localPosition.y / Height)
            return new Vector2(
                Mathf.Clamp01((localPosition.x - left) / OffsetWidth),
                Mathf.Clamp01((localPosition.y - bottom) / OffsetHeight)
            );
        }
    }
}